package js.web.center.script.core;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

import org.apache.log4j.Logger;

import js.web.center.core.config.JsWebConfig;
import js.web.center.script.utils.JsWebScriptUtils;
import js.web.center.utils.JsWebScriptHandlerCacheUtils;
/**
 * @author dowell
 *
 */
public class JsWebScriptEngineCore {
	private static Logger logger=Logger.getLogger(JsWebScriptEngineCore.class);
	/**
	 * 程序加载目录路径
	 */
	public static String basePath="";
	private int id;
	private boolean isDestory=true;
	private ScriptEngineManager engineManager=null;
	private ScriptEngine engine=null;
	private HashMap<String, Long> fileNames=new HashMap<>();
	public JsWebScriptEngineCore(){
		isDestory=false;
		this.engineManager=new ScriptEngineManager();
		this.engine=engineManager.getEngineByName("javascript");
		JsWebScriptUtils.scriptIds++;
		id=JsWebScriptUtils.scriptIds;
		JsWebScriptUtils.getInstance().addScriptEngineCore(id, this);
	}
	/**
	 * 获取所有初始化加载文件信息
	 * @return
	 */
	public ArrayList<String> getFiles(){
		ArrayList<String> arrayList=new ArrayList<>();
		Iterator<String> iterator = fileNames.keySet().iterator();
		while(iterator.hasNext()){
			arrayList.add(iterator.next());
		}
		return arrayList;
	} 
	/**
	 * 初始化脚本文件
	 * @param basePath 获取脚本文件路径
	 * @param name 类名
	 * @throws FileNotFoundException 
	 * @throws ScriptException 
	 * @throws UnsupportedEncodingException 
	 */
	public void init(String name) throws FileNotFoundException, ScriptException{
		File file=new File(basePath+name+JsWebConfig.CHECK_JS_TYPE);
		if(file.exists()){
			FileInputStream in = new FileInputStream(file);
			BufferedReader reader;
			try {
				reader = new BufferedReader(new InputStreamReader(in,JsWebConfig.DEFAULT_CHAR_CODE));
				this.engine.eval(reader);
			} catch (UnsupportedEncodingException e) {
				logger.error("JsWebScriptEngineCore ERROR:{}",e);
			}
			this.fileNames.put(name, file.lastModified());
		}else{
			logger.error("Not Find File ["+file.getAbsolutePath()+"]");
		}
	}
	/**
	 * 获取脚本id
	 * @return
	 */
	public int getId() {
		return id;
	}
	/**
	 * 是否需要内存回收
	 * @return
	 */
	public boolean isDestory() {
		return isDestory;
	}
	/**
	 * 关闭程序
	 */
	public void close(){
		if(this.engineManager!=null){
			this.engineManager=null;
			this.engine=null;
			this.fileNames.clear();
			this.fileNames=null;
			isDestory=true;
		}
	}
	/**
	 * 更新脚步文件
	 */
	public void refresh(){
		Iterator<Entry<String, Long>> iterator = this.fileNames.entrySet().iterator();
		while(iterator.hasNext()){
			Entry<String,Long> entry=iterator.next();
			File file=new File(basePath+entry.getKey()+JsWebConfig.CHECK_JS_TYPE);
			if(file.exists()){
				if(file.lastModified()!=entry.getValue()){
					this.fileNames.put(entry.getKey(), file.lastModified());
					try {
						FileInputStream in = new FileInputStream(file);
						BufferedReader reader;
						try {
							reader = new BufferedReader(new InputStreamReader(in,JsWebConfig.DEFAULT_CHAR_CODE));
							this.engine.eval(reader);
						} catch (UnsupportedEncodingException e) {
							logger.error("JsWebScriptEngineCore ERROR:{}",e);
						}
					} catch (FileNotFoundException e) {
						logger.error("JsWebScriptEngineCore ERROR:{}",e);
					} catch (ScriptException e) {
						logger.error("JsWebScriptEngineCore ERROR:{}",e);
					}
				}
			}else{
				this.fileNames.remove(entry.getKey());
				JsWebScriptEngineCore remove = JsWebScriptHandlerCacheUtils.hashMap.remove(entry.getKey().replace("web/", ""));
				remove.isDestory();
			}
		}
	}
	public void loadScirpt(String info){
		try {
			this.engine.eval(info);
		} catch (ScriptException e) {
			logger.error("JsWebScriptEngineCore ERROR:{}",e);
		}
	}
	/**
	 * 获取脚步文件路
	 * @return
	 */
	public String getBasePath(){
		return basePath;
	}
	/**
	 * 向脚本传递参数
	 * @param name 参数名
	 * @param params 参数
	 */
	public void appParams(String name,Object params){
		this.engine.put(name, params);
	}
	/**
	 * 运行脚本方法
	 * @param funName 方法名
	 * @param params 参数
	 * @return
	 * @throws NoSuchMethodException
	 * @throws ScriptException
	 */
	public Object function(String funName,Object ...params) throws NoSuchMethodException, ScriptException{
		Object back=null;
		if(this.engine instanceof Invocable){
			Invocable invocable=(Invocable) this.engine;
			back=invocable.invokeFunction(funName,params);
		}
		return back;
	}
}
